package com.distributed.tcp.service;

import com.distributed.tcp.config.TcpServerProperties;
import com.distributed.tcp.manager.DeviceConnectionManager;
import com.distributed.tcp.manager.MessageHandler;
import com.distributed.tcp.manager.MessageHandlerFactory;
import com.distributed.tcp.model.CommonResult;
import com.distributed.tcp.model.DeviceConnection;
import com.distributed.tcp.model.MessageForwardRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class DeviceMessageService {
    @Resource
    private DeviceConnectionManager connectionManager;
    
    @Resource
    private MessageHandlerFactory handlerFactory;
    
    @Resource
    private TcpServerProperties tcpProperties;

    @Resource
    private RestTemplate restTemplate; // 用于IP+端口直接转发


    /**
     * 发送消息到设备（自动处理跨主机转发）
     */
    public CommonResult<Boolean> sendMessageToDevice(String deviceId, String message) {
        // 1. 获取设备连接信息
        DeviceConnection connection = connectionManager.getConnectionByDeviceId(deviceId);
        if (connection == null) {
            return CommonResult.fail("设备未连接或已离线: " + deviceId);
        }

        // 2. 判断是否为本地连接
        if (connectionManager.isLocalConnection(connection)) {
            // 本地连接，直接发送
            return sendLocalMessage(deviceId, message);
        } else {
            // 跨主机连接，转发消息
            return forwardToRemote(connection, deviceId, message);
        }
    }

    /**
     * 本地发送消息
     */
    private CommonResult<Boolean> sendLocalMessage(String deviceCode, String message) {
        try {
            DeviceConnection connection = connectionManager.getLocalDeviceConnection(deviceCode);
            if (connection == null) {
                return CommonResult.fail("本地未找到设备连接: " + deviceCode);
            }

            // 使用对应端口的消息处理器发送消息
            MessageHandler handler = handlerFactory.getHandler(
                tcpProperties.getMessageHandlerMapping().getOrDefault(connection.getPort(), "messageExecute")
            );
            
            boolean success = handler.sendMessage(connection.getChannel(), message);
            if (success) {
                return CommonResult.success(true);
            } else {
                return CommonResult.fail("发送消息到设备失败: " + deviceCode);
            }
        } catch (Exception e) {
            log.error("发送本地消息失败", e);
            return CommonResult.fail("发送消息异常: " + e.getMessage());
        }
    }

    /**
     * 转发消息到远程主机（支持IP+端口直接转发和Nacos服务发现转发）
     */
    private CommonResult<Boolean> forwardToRemote(DeviceConnection connection, String deviceId, String message) {
        // 构建转发请求参数
        MessageForwardRequest request = new MessageForwardRequest();
        request.setDeviceId(deviceId);
        request.setMessage(message);
        request.setSourceHost(connection.getHost());
        request.setSourcePort(connection.getPort());

        // 重试配置
        int maxRetry = tcpProperties.getForward().getMaxRetry();
        int retryInterval = tcpProperties.getForward().getRetryInterval();

        for (int i = 0; i <= maxRetry; i++) {
            try {
                CommonResult<Boolean> result;
                //通过端口IP转发
                result = forwardByDirect(connection.getHost(), connection.getPort(), request);
                if (result.isSuccess() && Boolean.TRUE.equals(result.getData())) {
                    return CommonResult.success(true);
                }

                // 未达最大重试次数则等待重试
                if (i < maxRetry) {
                    log.warn("消息转发失败，将重试({}/{}): {}", i + 1, maxRetry, result.getMessage());
                    TimeUnit.MILLISECONDS.sleep(retryInterval);
                }
            } catch (Exception e) {
                log.error("转发失败（第{}次）", i + 1, e);
                if (i < maxRetry) {
                    try {
                        TimeUnit.MILLISECONDS.sleep(retryInterval);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }

        return CommonResult.fail("消息转发失败，已达最大重试次数");
    }

    /**
     * 处理其他实例转发过来的消息
     */
    public CommonResult<Boolean> handleForwardMessage(MessageForwardRequest request) {
        log.info("收到来自{}:{}的转发消息，设备:{}，内容:{}",
                request.getSourceHost(), request.getSourcePort(),
                request.getDeviceId(), request.getMessage());
        
        return sendLocalMessage(request.getDeviceId(), request.getMessage());
    }

    /**
     * 通过IP+端口直接转发
     */
    private CommonResult<Boolean> forwardByDirect(String host, int port, MessageForwardRequest request) {
        try {
            // 构建直接转发URL（使用配置中的URL模板）
            String url = String.format(
                    tcpProperties.getForward().getDirectUrlPrefix(),
                    host,
                    port
            );

            // 设置请求头（JSON格式）
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            //TODO TOKEN
            HttpEntity<MessageForwardRequest> httpEntity = new HttpEntity<>(request, headers);

            // 发送POST请求
            return restTemplate.postForObject(url, httpEntity, CommonResult.class);
        } catch (Exception e) {
            log.error("IP+端口直接转发失败（host: {}, port: {}）", host, port, e);
            return CommonResult.fail("直接转发失败: " + e.getMessage());
        }
    }

}
